package lab3;
import org.junit.Test;
import static org.junit.Assert.*;
public class ExerciseTest {
    
    @Test
    public void testExerciseConstructor() {
        Exercise exercise = new Exercise();
        assertEquals(0, exercise.size());
    }
    
   @Test
public void testContains() {
    Exercise exercise = new Exercise();
    
    // ==================== 等价类划分测试 ====================
    
    // 等价类1: 空练习集合
    BinaryOperation op1 = new BinaryOperation(5, 3, '+');
    assertFalse("EC1: 空练习集合不应该包含任何算式", exercise.contains(op1));
    
    // 等价类2: 包含相同算式的练习集合
    // 先添加一个特定算式到练习中
    exercise.generateAdditionExercise(1);
    BinaryOperation existingOp = exercise.getOperation(0);
    assertTrue("EC2: 练习应该包含已存在的算式", exercise.contains(existingOp));
    
    // 等价类3: 不包含该算式的练习集合
    BinaryOperation nonExistingOp = new BinaryOperation(99, 99, '+'); // 极不可能生成的算式
    assertFalse("EC3: 练习不应该包含不存在的算式", exercise.contains(nonExistingOp));
    
    // ==================== 边界值测试 ====================
    
    // 边界值1: 练习中只有一个算式
    Exercise singleExercise = new Exercise();
    singleExercise.generateAdditionExercise(1);
    BinaryOperation singleOp = singleExercise.getOperation(0);
    assertTrue("BV1: 单算式练习应该包含该算式", singleExercise.contains(singleOp));
    
    // 边界值2: 练习中有多个算式（测试第一个）
    Exercise multiExercise = new Exercise();
    multiExercise.generateAdditionExercise(5);
    BinaryOperation firstOp = multiExercise.getOperation(0);
    assertTrue("BV2: 多算式练习应该包含第一个算式", multiExercise.contains(firstOp));
    
    // 边界值3: 练习中有多个算式（测试最后一个）
    BinaryOperation lastOp = multiExercise.getOperation(4);
    assertTrue("BV3: 多算式练习应该包含最后一个算式", multiExercise.contains(lastOp));
    
    // 边界值4: 练习中有多个算式（测试中间位置）
    BinaryOperation middleOp = multiExercise.getOperation(2);
    assertTrue("BV4: 多算式练习应该包含中间位置的算式", multiExercise.contains(middleOp));
    
    // ==================== 特殊值测试 ====================
    
    // 特殊值1: null 值测试
    assertFalse("SV1: 练习不应该包含null", exercise.contains(null));
    
    // 特殊值2: 相同值但不同对象的算式
    BinaryOperation clonedOp = new BinaryOperation(
        existingOp.getLeftOperand(),
        existingOp.getRightOperand(),
        existingOp.getOperator()
    );
    assertTrue("SV2: 相同值的不同对象应该被认为是相等的", exercise.contains(clonedOp));
    
    // 特殊值3: 运算符不同的算式
    BinaryOperation differentOperator = new BinaryOperation(
        existingOp.getLeftOperand(),
        existingOp.getRightOperand(),
        '-'  // 不同的运算符
    );
    assertFalse("SV3: 运算符不同的算式应该被认为是不相等的", exercise.contains(differentOperator));
    
    // 特殊值4: 左操作数不同的算式
    BinaryOperation differentLeft = new BinaryOperation(
        existingOp.getLeftOperand() + 1,  // 不同的左操作数
        existingOp.getRightOperand(),
        existingOp.getOperator()
    );
    assertFalse("SV4: 左操作数不同的算式应该被认为是不相等的", exercise.contains(differentLeft));
    
    // 特殊值5: 右操作数不同的算式
    BinaryOperation differentRight = new BinaryOperation(
        existingOp.getLeftOperand(),
        existingOp.getRightOperand() + 1,  // 不同的右操作数
        existingOp.getOperator()
    );
    assertFalse("SV5: 右操作数不同的算式应该被认为是不相等的", exercise.contains(differentRight));
}
    
    @Test
    public void testGenerateAdditionExercise() {
        Exercise exercise = new Exercise();
        exercise.generateAdditionExercise(10);
        
        assertEquals(10, exercise.size());
        for (int i = 0; i < 10; i++) {
            BinaryOperation op = exercise.getOperation(i);
            assertEquals('+', op.getOperator());
        }
    }
    
    @Test
    public void testNoDuplicateOperations() {
        Exercise exercise = new Exercise();
        exercise.generateAdditionExercise(20);
        
        // 检查是否有重复的算式
        for (int i = 0; i < 20; i++) {
            for (int j = i + 1; j < 20; j++) {
                assertFalse(exercise.getOperation(i).equals(exercise.getOperation(j)));
            }
        }
    }
}